package com.huidu.bitrade.controller.lockOrder;

import cn.hutool.core.bean.BeanUtil;
import com.huidu.bitrade.constant.ActivityType;
import com.huidu.bitrade.constant.BooleanEnum;
import com.huidu.bitrade.constant.PageModel;
import com.huidu.bitrade.dto.LockedOrderDto;
import com.huidu.bitrade.entity.*;
import com.huidu.bitrade.exception.ServiceException;
import com.huidu.bitrade.service.ActivityService;
import com.huidu.bitrade.service.LockedOrderService;
import com.huidu.bitrade.service.MemberWalletService;
import com.huidu.bitrade.util.DateUtil;
import com.huidu.bitrade.util.MessageResult;
import com.huidu.bitrade.util.PredicateUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("lockOrder")
@Api(tags = "锁仓订单管理")
@RequiredArgsConstructor
public class LockedOerderController {
    private final ActivityService activityService;
    private final LockedOrderService lockedOrderService;
    private final MemberWalletService memberWalletService;

    @ApiOperation("添加锁仓订单")
    @PostMapping("/create")
    @Transactional(rollbackFor = Exception.class)
    public MessageResult create(LockedOrderDto lockedOrderDto) throws InvocationTargetException, IllegalAccessException {
        Activity activity = activityService.findById(lockedOrderDto.getActivityId());
        LockedOrder lo = new LockedOrder();
        BeanUtil.copyProperties(lockedOrderDto,lo);
        createLockOrder(activity, lo, lockedOrderDto.getAmount());
        lockedOrderService.save(lo);
        // 扣除接受币成交
        MemberWallet freezeWallet = memberWalletService.findByCoinUnitAndMemberId(activity.getAcceptUnit(),lockedOrderDto.getMemberId());
        // ToRelease 增加待释放余额( = 用户参与数量 * 释放倍数）
        memberWalletService.increaseToRelease(freezeWallet.getId(), lockedOrderDto.getAmount().multiply(activity.getReleaseTimes()));
        return MessageResult.success();
    }

    @ApiOperation("添加锁仓订单/扣除余额")
    @PostMapping("/createSubBalance")
    @Transactional(rollbackFor = Exception.class)
    public MessageResult createSubBalance(LockedOrderDto lockedOrderDto) throws ServiceException {
        Activity activity = activityService.findById(lockedOrderDto.getActivityId());
        LockedOrder lo = new LockedOrder();
        BeanUtil.copyProperties(lockedOrderDto,lo);
        createLockOrder(activity, lo, lockedOrderDto.getAmount());
        lockedOrderService.save(lo);
        // 扣除接受币成交
        MemberWallet freezeWallet = memberWalletService.findByCoinUnitAndMemberId(activity.getAcceptUnit(),lockedOrderDto.getMemberId());
        if(lockedOrderDto.getAmount().compareTo(freezeWallet.getBalance())>0){
            throw new ServiceException(activity.getAcceptUnit()+"余额不足");
        }
        //扣除余额
        memberWalletService.deductBalance(freezeWallet,lockedOrderDto.getAmount());
        // ToRelease 增加待释放余额( = 用户参与数量 * 释放倍数）
        memberWalletService.increaseToRelease(freezeWallet.getId(), lockedOrderDto.getAmount().multiply(activity.getReleaseTimes()));
        return MessageResult.success();
    }

    @ApiOperation("修改锁仓订单")
    @PostMapping("/update")
    public MessageResult update(@RequestParam("id")Long id ,@RequestParam("lockedDays") int lockedDays,
                                @RequestParam("originReleaseamount") BigDecimal originReleaseamount,
                                @RequestParam("currentReleaseamount") BigDecimal currentReleaseamount
    ) throws InvocationTargetException, IllegalAccessException {
        LockedOrder lo = lockedOrderService.findOne(id);
        Assert.notNull(lo, "未找到该订单！");
        lo.setLockedDays(lockedDays);
        lo.setOriginReleaseamount(originReleaseamount);
        lo.setCurrentReleaseamount(currentReleaseamount);
        lockedOrderService.save(lo);
        return MessageResult.success();
    }

    public static void createLockOrder(Activity activity, LockedOrder lo, BigDecimal amount) {
        lockOrder(activity, lo, amount);
    }

    public static void lockOrder(Activity activity, LockedOrder lo, BigDecimal amount) {
        Date currentDate = DateUtil.getCurrentDate();
        // 以日为周期的释放
        if(activity.getLockedPeriod() == 0) lo.setEndTime(DateUtil.dateAddDay(currentDate, activity.getLockedDays()));
        // 以周为周期的释放
        if(activity.getLockedPeriod() == 1) lo.setEndTime(DateUtil.dateAddDay(currentDate, activity.getLockedDays() * 7));
        // 以月为周期的释放
        if(activity.getLockedPeriod() == 2) lo.setEndTime(DateUtil.dateAddMonth(currentDate, activity.getLockedDays()));
        // 以年为周期的释放
        if(activity.getLockedPeriod() == 3) lo.setEndTime(DateUtil.dateAddYear(currentDate, activity.getLockedDays()));
        lo.setLockedDays(activity.getLockedDays());
        lo.setReleasedDays(0);
        lo.setReleaseUnit(activity.getLockedUnit());
        lo.setReleaseType(activity.getReleaseType());
        lo.setPeriod(activity.getLockedPeriod());
        lo.setLockedStatus(1); // 锁仓状态：释放中
        lo.setReleasePercent(activity.getReleasePercent());
        lo.setReleaseCurrentpercent(activity.getReleasePercent());
        lo.setImage(activity.getSmallImageUrl());
        lo.setTitle(activity.getTitle());
        lo.setTotalLocked(amount.multiply(activity.getReleaseTimes()));
        lo.setReleaseTimes(activity.getReleaseTimes());
        lo.setOriginReleaseamount(amount.multiply(activity.getReleaseTimes()).divide(BigDecimal.valueOf(activity.getLockedDays()), 8, RoundingMode.HALF_DOWN));
        lo.setCurrentReleaseamount(amount.multiply(activity.getReleaseTimes()).divide(BigDecimal.valueOf(activity.getLockedDays()), 8, RoundingMode.HALF_DOWN));
        lo.setTotalRelease(BigDecimal.ZERO);
        lo.setLockedInvite(activity.getMiningInvite());
        lo.setLockedInvitelimit(activity.getMiningInvitelimit());
    }


    @ApiOperation("查询锁仓活动")
    @GetMapping("/pageLockActivity")
    public MessageResult<Activity> pageLockActivity(PageModel pageModel) {
        if (pageModel.getProperty() == null) {
            //活动结束时间倒序排列
            List<String> list = new ArrayList<>();
            list.add("endTime");
            List<Sort.Direction> directions = new ArrayList<>();
            directions.add(Sort.Direction.DESC);
            pageModel.setProperty(list);
            pageModel.setDirection(directions);
        }

        ArrayList<BooleanExpression> booleanExpressions = new ArrayList<>();
        QActivity qActivity = QActivity.activity;
        booleanExpressions.add(qActivity.type.eq(ActivityType.LOCK));//锁仓
        booleanExpressions.add(qActivity.status.eq(BooleanEnum.IS_TRUE));//启用
        Predicate predicate = PredicateUtils.getPredicate(booleanExpressions);
        Page<Activity> all = activityService.findAll(predicate, pageModel.getPageable());
        MessageResult result = MessageResult.success();
        result.setData(all);
        return result;
    }

    @ApiOperation("查询锁仓活动订单")
    @GetMapping("/pageLockOrder/{activityId}")
    public MessageResult<LockedOrder> pageLockOrder(@PathVariable Long activityId, PageModel pageModel) {
        if (pageModel.getProperty() == null) {
            //活动结束时间倒序排列
            List<String> list = new ArrayList<>();
            list.add("createTime");
            List<Sort.Direction> directions = new ArrayList<>();
            directions.add(Sort.Direction.DESC);
            pageModel.setProperty(list);
            pageModel.setDirection(directions);
        }
        ArrayList<BooleanExpression> booleanExpressions = new ArrayList<>();
        QLockedOrder qLockedOrder = QLockedOrder.lockedOrder;
        booleanExpressions.add(qLockedOrder.activityId.eq(activityId));
        Predicate predicate = PredicateUtils.getPredicate(booleanExpressions);
        Page<LockedOrder> all = lockedOrderService.findAll(predicate, pageModel.getPageable());
        MessageResult result = MessageResult.success();
        result.setData(all);
        return result;
    }

}
